/* ----------------------------------------------------------------------
*
* Copyright (C) 2025 XiaoFei. All rights reserved.
*
* @file:        AiThinker_RD03.c
* @author:      XiaoFei
* @Date:        31-March-2025
* @Revision:    V1
* @Project:     XiaoFei BSP Library
*
* -------------------------------------------------------------------- */

#include "stm32f10x.h"
#include "XiaoFei_Delay.h"
#include "AiThinker_RD03.h"
#include "stdlib.h"
#include "string.h"

RD03_BufDef RD03_This;
unsigned char Cmd_WriCmd[14] = {0xfd, 0xfc, 0xfb, 0xfa, 0x04, 0x00, 0xff, 0x00, 0x01, 0x00, 0x04, 0x03, 0x02, 0x01};
unsigned char Cmd_MinDis[18] = {0xfd, 0xfc, 0xfb, 0xfa, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x02, 0x01};
unsigned char Cmd_MaxDis[18] = {0xfd, 0xfc, 0xfb, 0xfa, 0x08, 0x00, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x02, 0x01};
unsigned char Cmd_DelTim[18] = {0xfd, 0xfc, 0xfb, 0xfa, 0x08, 0x00, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x02, 0x01};
#if defined(RD03_V2)
unsigned char Cmd_KeepDa[12] = {0xfd, 0xfc, 0xfb, 0xfa, 0x02, 0x00, 0xfd, 0x00, 0x04, 0x03, 0x02, 0x01};
#endif
unsigned char Cmd_ReadDa[13] = {0xfd, 0xfc, 0xfb, 0xfa, 0x02, 0x00, 0xfe, 0x00, 0x04, 0x03, 0x02, 0x01, 0x00};
unsigned char Data_Hander[4] = {0xf4, 0xf3, 0xf2, 0xf1};

/* 
* @function: 	RD03_BufClear
* @parameter:	[in] RD03				    The handle of RD03.
* @parameter:	[in] ClThis				    Input 0x01 to clear all buffers, otherwise input 0x00.
*/
void RD03_BufClear(RD03_BufDef* RD03, unsigned char ClThis)
{
    RD03->len = 0;
    for (unsigned int i = 0; i < RD03->len_max; i++)
        RD03->buf[i] = 0;
    if (!(!ClThis))
    {
        RD03_This.len = 0;
        for (unsigned int i = 0; i < RD03_This.len_max; i++)
            RD03_This.buf[i] = 0;
    }
}

/* 
* @function: 	RD03_BufGet
* @parameter:	[in] RD03				    The handle of RD03.
* @parameter:	[in] us				        The interval for obtaining two adjacent pointers.
* @return:		Return 0x01 if the data has get successful, otherwise return 0x00.
*/
unsigned char RD03_BufGet(RD03_BufDef* RD03, unsigned int us)
{
    unsigned int len = RD03_This.len;
    XiaoFei_Delay_us(us);
    if ((len == RD03_This.len) && (RD03_This.len != 0))
    {
        RD03->len = RD03_This.len;
        RD03->len_max = RD03_This.len_max;
        for (unsigned int i = 0; i < RD03->len_max; i++)
            RD03->buf[i] = RD03_This.buf[i];
        return 0x01;
    }
    return 0x00;
}

/* 
* @function: 	RD03_Init
* @parameter:	[out] RD03				    The handle of RD03.
*/
void RD03_Init(RD03_BufDef* RD03)
{
    RD03_RCC_Usart(1);
    RD03_RCC_TX(1);
    RD03_RCC_RX(1);
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Pin = RD03_Pin_TX;
    GPIO_Init(RD03_GPIO_TX, &GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Pin = RD03_Pin_RX;
    GPIO_Init(RD03_GPIO_RX, &GPIO_InitStructure);
    USART_InitTypeDef USART_InitStructure;
    USART_InitStructure.USART_BaudRate = RD03_BaudRate;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(RD03_Usart, &USART_InitStructure);
    USART_ITConfig(RD03_Usart, USART_IT_RXNE, ENABLE);
    NVIC_PriorityGroupConfig(RD03_Group);
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = RD03_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = RD03_ITPre;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = RD03_ITSub;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    USART_Cmd(RD03_Usart, ENABLE);
    RD03->len = 0;
    RD03_This.len = 0;
    #if defined(RD03_V1)
        RD03->len_max = 90;
        RD03_This.len_max = 90;
    #elif defined(RD03_V2)
        RD03->len_max = 300;
        RD03_This.len_max = 300;
    #endif
    for(unsigned int i=0; i < RD03->len_max; i++)
    {
        RD03->buf[i] = 0x00;
        RD03_This.buf[i] = 0x00;
    }
}

/* 
* @function: 	RD03_Send
* @parameter:	[in] str					 The data will be send to RD03.
* @parameter:	[in] num					 The size of the data.
*/
static void RD03_Send(unsigned char* str, unsigned int num)
{
    for (unsigned int i = 0; i < num; i++)
    {
        USART_SendData(RD03_Usart, str[i]);
        while (USART_GetFlagStatus(RD03_Usart, USART_FLAG_TXE) == RESET);
    }
    while (USART_GetFlagStatus(RD03_Usart, USART_FLAG_TC) == RESET);
}

/* 
* @function: 	RD03_SetMood
* @parameter:	[in] RD03					 The handle of RD03.
* @parameter:	[in] Mood					 The mode will be set to RD03.
*/
void RD03_SetMood(RD03_BufDef* RD03, RD03_MoodDef Mood)
{
    unsigned char Cmd_SetMod[18] = {0xfd, 0xfc, 0xfb, 0xfa, 0x08, 0x00, 0x12, 0x00, 0x00, 0x00, (unsigned char)Mood, 0x00, 0x00, 0x00, 0x04, 0x03, 0x02, 0x01};
	RD03_BufClear(RD03, 1);
    RD03_Send(Cmd_WriCmd, sizeof(Cmd_WriCmd));
    XiaoFei_Delay_ms(150);
    RD03_BufClear(RD03, 1);
    RD03_Send(Cmd_WriCmd, sizeof(Cmd_WriCmd));
    RD03_BufClear(RD03, 1);
    RD03_Send(Cmd_MinDis, sizeof(Cmd_MinDis));
    RD03_BufClear(RD03, 1);
    RD03_Send(Cmd_MaxDis, sizeof(Cmd_MaxDis));
    RD03_BufClear(RD03, 1);
    RD03_Send(Cmd_DelTim, sizeof(Cmd_DelTim));
    RD03_BufClear(RD03, 1);
    RD03_Send(Cmd_SetMod, sizeof(Cmd_SetMod));
    RD03_BufClear(RD03, 1);
    #if defined(RD03_V2)
        RD03_Send(Cmd_KeepDa, sizeof(Cmd_KeepDa));
        RD03_BufClear(RD03, 1);
    #endif
    RD03_Send(Cmd_ReadDa, sizeof(Cmd_ReadDa));
    RD03_BufClear(RD03, 1);
}

/* 
* @function: 	RD03_RunningData
* @parameter:	[in] RD03					 The handle of RD03.
* @parameter:	[in] Data					 The data decoding result of RD03 in running mode.
*/
void RD03_RunningData(RD03_BufDef* RD03, RD03_RunDataDef* Data)
{
    if (RD03->len < strlen("OFF"))
    {
        Data->state = 0x00;
        Data->range = 0;
        return;
    }
    char *temp = NULL;
    #if defined(RD03_V1)
        temp = strstr((char*)RD03->buf, "Range");
        if (temp != NULL)
        {
            Data->state = 0x01;
            Data->range = atoi(temp + strlen("Range:"));
            RD03_BufClear(RD03, 1);
            return;
        }
    #elif defined(RD03_V2)
        temp = strstr((char*)RD03->buf, "distance");
        if (temp != NULL)
        {
            Data->state = 0x01;
            Data->range = atoi(temp + strlen("distance:"));
            RD03_BufClear(RD03, 1);
            return;
        }
    #endif
    else
    {
        Data->state = 0x00;
        Data->range = 0;
        RD03_BufClear(RD03, 1);
        return;
    }
}

/* 
* @function: 	RD03_ReportData
* @parameter:	[in] RD03					 The handle of RD03.
* @parameter:	[in] Data					 The data decoding result of RD03 in report mode.
*/
void RD03_ReportData(RD03_BufDef* RD03, RD03_RepDataDef* Data)
{
    #if defined(RD03_V1)
        #define RD03_Debug_len      80
        #define RD03_Enerage_Size   16
        #define RD03_Debug2_flu     41
    #elif defined(RD03_V2)
        #define RD03_Debug_len      200
        #define RD03_Enerage_Size   32
        #define RD03_Debug2_flu     137
    #endif
    unsigned int header_offset = 0;
    if (RD03->len < RD03_Debug_len)
    {
        Data->state = 0x00;
        Data->range = 0;
        for (unsigned char i = 0; i < RD03_Enerage_Size; i++)
            Data->energy[i] = 0;
        return;
    }
    char *temp = NULL;
    temp = strstr((char*)RD03->buf, (char*)Data_Hander);
    if (temp == NULL)
    {
        Data->state = 0x00;
        Data->range = 0;
        for (unsigned char i = 0; i < RD03_Enerage_Size; i++)
            Data->energy[i] = 0;
        goto RD03_Err_Deal;
    }
    header_offset = (unsigned int)(temp - (char *)RD03->buf);
    if (header_offset + RD03_Debug2_flu + 4 > RD03->len)
        goto RD03_Err_Deal;
    if (*((unsigned char*)temp + RD03_Debug2_flu) != 0xF8)
        goto RD03_Err_Deal;
    if (*((unsigned char*)temp + RD03_Debug2_flu + 1) != 0xF7)
        goto RD03_Err_Deal;
    if (*((unsigned char*)temp + RD03_Debug2_flu + 2) != 0xF6)
        goto RD03_Err_Deal;
    if (*((unsigned char*)temp + RD03_Debug2_flu + 3) != 0xF5)
        goto RD03_Err_Deal;
    Data->state = *((unsigned char*)temp + 6);
    Data->range = (unsigned int)(*((unsigned char*)temp + 7)) + 256 * (*((unsigned char*)temp + 8));
    for (unsigned char i = 0; i < RD03_Enerage_Size; i++)
    {
        #if defined(RD03_V1)
            Data->energy[i] = (unsigned int)(*((unsigned char*)temp + 9 + 2 * i)) 
                                + 256 * (*((unsigned char*)temp + 10 + 2 * i));
        #elif defined(RD03_V2)
            Data->energy[i] = (unsigned int)(*((unsigned char*)temp + 9 + 4 * i)) 
                                + 256 * (*((unsigned char*)temp + 10 + 4 * i))
                                + 65536* (unsigned int)(*((unsigned char*)temp + 11 + 4 * i)) 
                                + 16777216 * (*((unsigned char*)temp + 12 + 4 * i));
        #endif
    }
    RD03_BufClear(RD03, 1);
    return;
    RD03_Err_Deal:
        RD03_BufClear(RD03, 1);
        return;
    #undef RD03_Debug_len    
    #undef RD03_Enerage_Size 
    #undef RD03_Debug2_flu   
}

/* 
* @function: 	RD03_IRQHandler
* @callback:	The function will be callback when get the data from RD03.
*/
void RD03_IRQHandler(void)
{
    if (USART_GetFlagStatus(RD03_Usart, USART_FLAG_RXNE) == SET)
    {
        USART_ClearITPendingBit(RD03_Usart, USART_IT_RXNE);
        RD03_This.buf[RD03_This.len] = USART_ReceiveData(RD03_Usart);
        if (RD03_This.len < RD03_This.len_max)
            RD03_This.len++;
    }
}


